package ch.christianschweizer.apps.ereservation.model;

import javax.persistence.Basic;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Version;

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class User implements Identifiable {

	public static abstract class UserBuilder<T extends User> {

		private String firstName;
		private String lastName;
		private String email;
		private String phoneNr;
		private Address address;

		public UserBuilder<T> firstName(String firstName) {
			this.firstName = firstName;
			return this;
		}

		public UserBuilder<T> lastName(String lastName) {
			this.lastName = lastName;
			return this;
		}

		public UserBuilder<T> email(String email) {
			this.email = email;
			return this;
		}

		public UserBuilder<T> phoneNr(String phoneNr) {
			this.phoneNr = phoneNr;
			return this;
		}

		public UserBuilder<T> address(Address address) {
			this.address = address;
			return this;
		}

		public abstract T build();

	}

	@Id
	@GeneratedValue
	private Long id;

	@Version
	private long version;

	@Basic
	private String firstName;

	@Basic
	private String lastName;

	@Basic
	private String email;

	@Basic
	private String phoneNr;

	@Embedded
	private Address address;

	protected User() {
	}

	protected User(UserBuilder<? extends User> builder) {
		firstName = builder.firstName;
		lastName = builder.lastName;
		email = builder.email;
		phoneNr = builder.phoneNr;
		address = builder.address;
	}

	@Override
	public Long getUniqueIdentifier() {
		return id;
	}

	public long getVersion() {
		return version;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPhoneNr() {
		return phoneNr;
	}

	public void setPhoneNr(String phoneNr) {
		this.phoneNr = phoneNr;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", firstName=" + firstName + ", lastName="
				+ lastName + ", email=" + email + ", phoneNr=" + phoneNr
				+ ", address=" + address + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((address == null) ? 0 : address.hashCode());
		result = prime * result + ((email == null) ? 0 : email.hashCode());
		result = prime * result
				+ ((firstName == null) ? 0 : firstName.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result
				+ ((lastName == null) ? 0 : lastName.hashCode());
		result = prime * result + ((phoneNr == null) ? 0 : phoneNr.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		User other = (User) obj;
		if (address == null) {
			if (other.address != null) {
				return false;
			}
		} else if (!address.equals(other.address)) {
			return false;
		}
		if (email == null) {
			if (other.email != null) {
				return false;
			}
		} else if (!email.equals(other.email)) {
			return false;
		}
		if (firstName == null) {
			if (other.firstName != null) {
				return false;
			}
		} else if (!firstName.equals(other.firstName)) {
			return false;
		}
		if (id == null) {
			if (other.id != null) {
				return false;
			}
		} else if (!id.equals(other.id)) {
			return false;
		}
		if (lastName == null) {
			if (other.lastName != null) {
				return false;
			}
		} else if (!lastName.equals(other.lastName)) {
			return false;
		}
		if (phoneNr == null) {
			if (other.phoneNr != null) {
				return false;
			}
		} else if (!phoneNr.equals(other.phoneNr)) {
			return false;
		}
		return true;
	}

}
